// 该 ts 文件需要引入一个 superagent 类库，而该类库是使用 js 写的，直接引用会报错
// ts 文件在引用 js 文件时，对类型的判断会报错，所以中间需要一个由 该js 文件翻译后的 ts 文件，然后再引用这个 ts 文件
// 该报错会提示安装 `npm install @types/superagent` 执行就可以了
// 相当于：ts -> .d.ts 翻译文件 -> js
import superagent from "superagent";
import fs from "fs";
import path from "path";
import LycAnalyzer from "./analyzer";

// 分析器约束接口
export interface Analyzer {
  analyzer: (html: string, filePath: string) => string;
}

class Crowller {
  private filePath = path.resolve(__dirname, "../../data/course.json");

  // 获取网页原始的 html
  private async getRawHtml() {
    const result = await superagent.get(this.url);
    return result.text;
  }

  // 爬虫所有的异步逻辑都写成 async await 形式是为了函数间的解耦
  private async initSpiderProcess() {
    const html = await this.getRawHtml();
    const fileContent = this.analyzer.analyzer(html, this.filePath);
    this.writeFile(fileContent);
  }

  // 写入文件
  private writeFile(fileContent: string) {
    // 写入文件，写入的数据必须为字符串类型的数据，所以要把对象类型的数据 JSON.stringify 处理
    fs.writeFileSync(this.filePath, fileContent);
  }

  constructor(private url: string, private analyzer: Analyzer) {
    // private analyzer: any 表示
    // this.analyzer: any = analyzer
    this.initSpiderProcess();
  }
}

export default Crowller;

const analyzer = LycAnalyzer.getInstance();
// 多页面爬虫
// for (let i = 2; i < 113; i++) {
//   let url = `http://www.xxx.html`;
//   new Crowller(url, analyzer);
// }
// 单页面爬虫
const url = `https://www.imooc.com/`;
new Crowller(url, analyzer);
